package lv.solcraft.replication.server.model;

import java.util.Date;

import lv.solcraft.replication.server.dao.OperDataAccess;
import lv.solcraft.replication.server.dao.OperSiteDataAccessFactory;

import org.springframework.util.Assert;

import com.sleepycat.persist.model.Entity;
import com.sleepycat.persist.model.PrimaryKey;
import com.sleepycat.persist.model.Relationship;
import com.sleepycat.persist.model.SecondaryKey;

@Entity
public class OperSite {

    @PrimaryKey
    private OperId id;

    private long siteId;

    private OperState state;

    private String message = "";

    private Date createdDate;

    @SecondaryKey(relate = Relationship.MANY_TO_ONE)
    private Record record;

    transient OperDataAccess operDataAccess;

    transient OperSiteDataAccessFactory operSiteDataAccessFactory;

    private transient OperState originalState;

    /**
     * For persistence only
     */
    @Deprecated
    protected OperSite() {
    }

    /**
     * Creates oper with id and in NEW state
     * 
     * @param siteId
     * 
     * @param operState
     */
    protected OperSite(OperId id, Record record, long siteId, OperState operState) {
        Assert.notNull(id, "Can not create oper site with null oper id");
        Assert.notNull(record, "Can not create oper site with null record");
        Assert.notNull(operState, "Can not create oper site with null state");
        this.record = record;
        this.id = id;
        this.createdDate = new Date();
        this.state = operState;
        this.siteId = siteId;
    }

    public OperId getId() {
        return id;
    }

    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        Assert.notNull(message, "OperSite message can not be null");
        this.message = message;
    }

    public Date getCreatedDate() {
        return createdDate;
    }

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + ((id == null) ? 0 : id.hashCode());
        return result;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        final OperSite other = (OperSite) obj;
        if (id == null) {
            if (other.id != null)
                return false;
        } else if (!id.equals(other.id))
            return false;
        return true;
    }

    @Override
    public String toString() {
        return id + ", " + record;
    }

    public Record getRecord() {
        return record;
    }

    public OperState getState() {
        return state;
    }

    public void setState(OperState newState) {
        if (this.state != newState && this.originalState == null) {
            // remember only really original state, not intermmediates
            this.originalState = this.state;
        }
        this.state = newState;
    }

    public void persist() {
        if (originalState != null) {
            operSiteDataAccessFactory.getInstance(siteId, originalState).delete(id);
        }
        operSiteDataAccessFactory.getInstance(siteId, state).persist(this);
    }

    public void delete() {
        if (originalState != null) {
            operSiteDataAccessFactory.getInstance(siteId, originalState).delete(id);
        }
        operSiteDataAccessFactory.getInstance(siteId, state).delete(id);
    }

    public Oper getOper() {
        return operDataAccess.find(id);
    }

    public long getSiteId() {
        return siteId;
    }

    public void inject(OperDataAccess operDataAccess, OperSiteDataAccessFactory operSiteDataAccessFactory) {
        this.operDataAccess = operDataAccess;
        this.operSiteDataAccessFactory = operSiteDataAccessFactory;
    }
}
